/**
 * DO NOT REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Contributor(s):
 *
 * The Original Software is SimpleDBM (www.simpledbm.org).
 * The Initial Developer of the Original Software is Dibyendu Majumdar.
 *
 * Portions Copyright 2005-2014 Dibyendu Majumdar. All Rights Reserved.
 *
 * The contents of this file are subject to the terms of the
 * Apache License Version 2 (the "APL"). You may not use this
 * file except in compliance with the License. A copy of the
 * APL may be obtained from:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the APL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the APL, the GPL or the LGPL.
 *
 * Copies of GPL and LGPL may be obtained from:
 * http://www.gnu.org/licenses/license-list.html
 */
package org.simpledbm.junit;

import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;

/**
 * Extends JUnit test case to provide basic support for handling multi-threaded
 * tests.
 * 
 * @author dibyendumajumdar
 */
public abstract class SimpleDBMTestCase extends TestCase {

    TestResult testResult;
    volatile boolean threadFailed;

    public SimpleDBMTestCase() {
    }

    public SimpleDBMTestCase(String arg0) {
        super(arg0);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        threadFailed = false;
    }

    protected final boolean hasThreadFailures() {
        return threadFailed;
    }

    @Override
    public void run(TestResult result) {
        this.testResult = result;
        super.run(result);
        this.testResult = null;
    }

    class SimpleDBMTestRunnable implements Runnable {

        final Test test;
        final TestResult result;
        final Runnable runnable;

        SimpleDBMTestRunnable(Test test, TestResult result, Runnable runnable) {
            this.test = test;
            this.result = result;
            this.runnable = runnable;
        }

        public void run() {
            try {
                runnable.run();
            } catch (Throwable t) {
                setThreadFailed(Thread.currentThread(), t);
            }
        }

        private final void setThreadFailed(Thread thread, Throwable exception) {
            if (exception instanceof AssertionFailedError) {
                result.addFailure(test, (AssertionFailedError) exception);
            } else {
                result.addError(test, exception);
            }
            threadFailed = true;
        }

    }

    protected Runnable getTestRunnable(Runnable runnable) {
        assertNotNull(testResult);
        return new SimpleDBMTestRunnable(this, testResult, runnable);
    }

}
